/*
 * @Descripttion: 实现setState方法(只实现同步)以及简易的和合成事件
 * @Author: lukasavage
 * @Date: 2021-11-13 00:51:43
 * @LastEditors: lukasavage
 * @LastEditTime: 2022-09-16 21:40:34
 */

import { compareTwoVdom, findDOM } from './react-dom3';

function shouldUpdate(classInstance, newState) {
	// 替换state,强制更新UI
	classInstance.state = newState;
	classInstance.forceUpdate();
}
class Updater {
	constructor(classInstance) {
		this.classInstance = classInstance;
		this.pendingState = [];
		this.callbacks = [];
	}
	addState(partialState, callback) {
		this.pendingState.push(partialState);
		if (callback && typeof callback === 'function') {
			this.callbacks.push(callback);
		}
		this.emitUpdate();
	}
	emitUpdate() {
		this.updateComponent();
	}
	updateComponent() {
		const { classInstance, pendingState, callbacks } = this;
		if (pendingState.length) {
			shouldUpdate(classInstance, this.getState());
		}
		if (callbacks.length) {
			callbacks.forEach(item => item());
			callbacks.length = 0;
		}
	}
	getState() {
		let newState;
		const {
			classInstance: { state },
			pendingState,
		} = this;
		pendingState.forEach(item => {
			if (typeof item === 'function') {
				item = item(state);
			}
			newState = { ...state, ...item };
		});
		pendingState.length = 0;
		return newState;
	}
}
export class Component {
	static isReactComponent = true;
	constructor(props) {
		this.props = props;
		this.state = {};
		this.updater = new Updater(this);
	}
	setState(partialState) {
		this.updater.addState(partialState);
	}
	forceUpdate() {
		// 获取此组件上一次render渲染出来的虚拟DOM
		const oldRenderVdom = this.oldRenderVdom;
		const oldDOM = findDOM(oldRenderVdom);
		const newVdom = this.render();
		compareTwoVdom(oldDOM.parentNode, oldRenderVdom, newVdom);
		this.oldRenderVdom = newVdom;
	}
}
